package org.dtrd.modules.doctor.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.dtrd.common.exception.JeecgBootException;
import org.dtrd.common.system.vo.LoginUser;
import org.dtrd.common.util.DateUtils;
import org.dtrd.common.util.JaxbUtil;
import org.dtrd.config.common.PathUtil;
import org.dtrd.config.system.Constant;
import org.dtrd.config.system.Constant.*;
import org.dtrd.config.wechat.api.impl.WechatApi;
import org.dtrd.config.wechat.config.WechatConstant;
import org.dtrd.config.wechat.config.WechatConstant.OfficialAccountTag;
import org.dtrd.config.wechat.config.WechatUtil;
import org.dtrd.config.wechat.entity.bean.AccessToken;
import org.dtrd.config.wechat.entity.bean.WechatQrCodeTicket;
import org.dtrd.config.wechat.entity.bean.officialaccount.WechatOaQrCodeScene;
import org.dtrd.config.wechat.entity.bean.officialaccount.WechatOfficialAccountUserInfo;
import org.dtrd.config.wechat.entity.response.WechatResponse;
import org.dtrd.config.wechat.entity.response.WxUnionidResp;
import org.dtrd.modules.control.entity.bean.PatientTargetReachStandardAvgRateDaily;
import org.dtrd.modules.control.service.IDtrdEntRdSigninTargetService;
import org.dtrd.modules.dict.service.IDtrdEntRdDicDistrictService;
import org.dtrd.modules.doctor.entity.bean.*;
import org.dtrd.modules.doctor.entity.po.DtrdEntRdDoctor;
import org.dtrd.modules.doctor.entity.po.DtrdEntRdDoctorStatisticInfo;
import org.dtrd.modules.doctor.entity.po.DtrdEntRdDoctorTeam;
import org.dtrd.modules.doctor.entity.po.DtrdRlDoctorPatient;
import org.dtrd.modules.doctor.entity.request.DoctorInfoRequest;
import org.dtrd.modules.doctor.entity.request.DoctorPageRequest;
import org.dtrd.modules.doctor.entity.request.SearchPatientRequest;
import org.dtrd.modules.doctor.entity.request.UpdateTeamDoctorRequest;
import org.dtrd.modules.doctor.mapper.DtrdEntRdDoctorMapper;
import org.dtrd.modules.doctor.service.*;
import org.dtrd.modules.flup.service.IDtrdEntRdFlupAppointmentRecordService;
import org.dtrd.modules.organization.entity.bean.OrganizationListInfo;
import org.dtrd.modules.organization.entity.po.DtrdEntRdOrganization;
import org.dtrd.modules.organization.service.IDtrdEntRdOrganizationService;
import org.dtrd.modules.organization.service.IDtrdRlDoctorOrganizationService;
import org.dtrd.modules.patient.entity.bean.PatientInfo;
import org.dtrd.modules.patient.entity.po.DtrdEntRdPatient;
import org.dtrd.modules.patient.entity.po.DtrdRlGroupPatient;
import org.dtrd.modules.patient.service.IDtrdEntRdPatientService;
import org.dtrd.modules.patient.service.IDtrdRlGroupPatientService;
import org.dtrd.modules.record.service.ISugarRecordService;
import org.dtrd.modules.service.entity.po.DtrdRlPackagePatient;
import org.dtrd.modules.service.service.IDtrdRlPackagePatientService;
import org.dtrd.modules.shop.entity.po.DtrdEntShcRdOrder;
import org.dtrd.modules.shop.service.IDtrdEntShcRdOrderService;
import org.dtrd.modules.shop.service.IDtrdEntShcRdGlucometerGetService;
import org.dtrd.modules.system.entity.SysUser;
import org.dtrd.modules.system.entity.bean.weixin.WxEventPushBean;
import org.dtrd.modules.system.entity.bean.weixin.WxPassiveResp;
import org.dtrd.modules.util.ShiroUtil;
import org.dtrd.common.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static org.dtrd.config.system.Constant.DoctorType.DEPARTMENT_DOCTOR;
import static org.dtrd.config.system.Constant.Group.NO_GROUP;

/**
 * <p>
 * 医生表 服务实现类
 * </p>
 *
 * @author QR
 * @since 2021-11-30 15:09:18
 */
@Slf4j
@Service
@DS("multi-datasource1")
public class DtrdEntRdDoctorServiceImpl extends ServiceImpl<DtrdEntRdDoctorMapper, DtrdEntRdDoctor> implements IDtrdEntRdDoctorService {

    @Autowired
    private IDtrdEntRdDoctorTeamService doctorTeamService;
    @Autowired
    private IDtrdRlDoctorOrganizationService doctorOrgRlService;
    @Autowired
    private IDtrdEntRdOrganizationService organizationService;
    @Autowired
    private IDtrdEntRdPatientService patientService;
    @Autowired
    private IDtrdRlGroupPatientService groupPatientService;
    @Autowired
    private IDtrdRlPackagePatientService packagePatientService;
    @Autowired
    private IDtrdRlDoctorPatientService doctorPatientRlService;
    @Autowired
    private IDtrdEntRdFlupAppointmentRecordService flupAppointmentRecordService;
    @Autowired
    private IDtrdEntRdDicDistrictService districtInfoService;
    @Autowired
    private IDtrdRlDoctorTeamDoctorService doctorTeamDoctorService;
    @Autowired
    private IDtrdEntRdSigninTargetService targetService;
    @Autowired
    private ISugarRecordService sugarRecordService;
    @Autowired
    private IDtrdEntRdDoctorStatisticInfoService doctorStatisticInfoService;
    @Autowired
    private IDtrdEntShcRdOrderService orderService;
    @Autowired
    private IDtrdEntShcRdGlucometerGetService glucometerGetService;

    @Autowired
    @Lazy
    private WechatApi wechatApi;

//    @Override
//    public boolean save(DtrdEntRdDoctor entity) {
//        boolean save = super.save(entity);
//        if (save) {
//            sendQrCodeGenerateEvent(entity);
//        }
//        return save;
//    }

//    private void sendQrCodeGenerateEvent(DtrdEntRdDoctor doctor) {
//        WechatQrCodeTicket addPatientQrCodeTicket = wechatApi.createUserQrCode(doctor.getDataId(), QRCODE_TYPE.DOCTOR_ADD_PATIENT.getType(), null);
//        if (addPatientQrCodeTicket != null) {
//            String addPatientQrCode = addPatientQrCodeTicket != null ? addPatientQrCodeTicket.getQrCodeUrl() : null;
//            log.info("DtrdEntRdDoctorServiceImpl.sendQrCodeGenerateEvent.[doctorId] addPatientQrCode=" + addPatientQrCodeTicket);
//            doctor.setQrcodeAddPatient(addPatientQrCode);
//            doctor.setWxOaQrcodeSourceUrl(addPatientQrCodeTicket.getUrl());
//        }
//        WechatQrCodeTicket addTeamQrCodeTicket = wechatApi.createUserQrCode(doctor.getDataId(), QRCODE_TYPE.DOCTOR_ADD_TEAM.getType(), null);
//        String addTeamQrCode = addTeamQrCodeTicket != null ? addTeamQrCodeTicket.getQrCodeUrl() : null;
//        log.info("DtrdEntRdDoctorServiceImpl.sendQrCodeGenerateEvent.[doctorId] addTeamQrCode=" + addTeamQrCode);
//        doctor.setQrcodeAddTeam(addTeamQrCode);
//        updateById(doctor);
//    }

    /**
     * 返回微信内容
     * https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Passive_user_reply_message.html#0
     */
    @Override
    public String handleQRCodeEvent(WxEventPushBean wxEventPushBean) {
        log.info("DtrdEntRdDoctorServiceImpl.handleQRCodeEvent, wxEvent: {}", wxEventPushBean);
        String eventKey = wxEventPushBean.getEventKey();
        String openId = wxEventPushBean.getFromUserName();
        if (StrUtil.isBlank(eventKey)) {
            log.info("DtrdEntRdDoctorServiceImpl.handleQRCodeEvent: 二维码内容为空 搜索关注");
            // 搜索关注，无法判断身份 ，不作处理
            return "";
        }
        WxUnionidResp unionidResp = wechatApi.getUnionid(openId);
        String unionid = unionidResp != null ? unionidResp.getUnionid() : null;
        // 扫描回调传值可能会以qrscene_ 开头
        String prefix = "qrscene_";
        if (eventKey.startsWith(prefix)) {
            eventKey = eventKey.substring(prefix.length());
        }
        log.info("DtrdEntRdDoctorServiceImpl.handleQRCodeEvent.[wxEventPushBean] eventKey=" + eventKey);
        WechatOaQrCodeScene qrCodeContent = JSONUtil.toBean(eventKey, WechatOaQrCodeScene.class);
        // 处理对应二维码逻辑
        // 处理反馈微信信息
        WxPassiveResp resp = new WxPassiveResp(wxEventPushBean);
        // 二维码中包含信息
        String doctorName;
        Integer scanDoctorId, doctorId;
        // 扫描者信息
        String scanDoctorName, scanPatientName;
        Integer scanPatientId, patientId;
        if (qrCodeContent.getQrCodeType() == QRCODE_TYPE.PATIENT.getType()) {
            // 扫描患者二维码
            //  医生扫描患者二维码
            patientId = qrCodeContent.getUserId();
            DtrdEntRdPatient patient = patientService.getById(qrCodeContent.getUserId());
            if (patient == null) {
                // 患者ID数据错误 不作处理
                return "";
            } else {
                DoctorInfo doctorInfo = getDoctorByUnionid(unionid);
                if (doctorInfo == null) {
                    // 未找到扫描id的医生记录 不作处理
                    log.info("DtrdEntRdDoctorServiceImpl.handleQRCodeEvent.[wxEventPushBean]  未找到扫描id的医生记录 不作处理 ");
                    return "";
                } else {
                    scanDoctorId = doctorInfo.getDataId();
                    scanDoctorName = doctorInfo.getDoctorsName();
                }
                // 处理医患关系
                doctorPatientRlService.saveOrUpdateDoctorPatientRelation(scanDoctorId, patientId, DoctorPatientRelationType.ADD_BY_SCAN_PATIENT.getType());
                patient.setDoctorId(scanDoctorId);
                patientService.updateById(patient);
                // 处理微信模板消息
//                 发送给扫描医生相应消息
                if (patient.getWxOaOpenid() != null) {
                    wechatApi.sendBindDoctorMsg(scanDoctorName, PathUtil.getChatroomUrl(USER_CATEGORY.USER_PATIENT.getUser(), patient.getDataId() + "", doctorPatientRlService.getChatroomIdByPatientId(patient.getDataId(), scanDoctorId)), patient.getWxOaOpenid());
                }
                // 处理返回微信消息
                String content = scanDoctorName + "医生为您服务!";
                return JaxbUtil.converTomXml(resp.buildText(WechatConstant.MsgType.text, content));
            }
        } else if (qrCodeContent.getQrCodeType() == QRCODE_TYPE.ORDER.getType()) {
            // 扫描订单二维码 将订单状态置为已完成
            DoctorInfo doctorInfo = getDoctorByUnionid(unionid);
            if (doctorInfo == null) {
                // 非医生扫描 不作处理
                return "";
            }
            String orderId = qrCodeContent.getOthers();
            boolean result = false;
            if (StrUtil.isNotBlank(orderId)) {
                DtrdEntShcRdOrder order = orderService.getById(orderId);
                if (order != null) {
                    result = orderService.completeOrder(orderId);
                    if (result) {
                        JSONObject addGetRecord = glucometerGetService.addGetRecord(order, doctorInfo);
                        if (addGetRecord.getBoolean("status").equals(true)) {
                            return JaxbUtil.converTomXml(resp.buildText(WechatConstant.MsgType.text, "绑定成功"));
                        } else {
                            return JaxbUtil.converTomXml(resp.buildText(WechatConstant.MsgType.text, addGetRecord.getString("error")));
                        }
                    }
                }
            }
            return JaxbUtil.converTomXml(resp.buildText(WechatConstant.MsgType.text, "扫描失败"));
        } else {
            // 扫描医生二维码
            doctorId = qrCodeContent.getUserId();
            DtrdEntRdDoctor doctor = getById(qrCodeContent.getUserId());
            doctorName = doctor == null ? null : doctor.getDoctorsName();
            if (qrCodeContent.getQrCodeType() == QRCODE_TYPE.DOCTOR_ADD_TEAM.getType()) {
                log.info("DtrdEntRdDoctorServiceImpl.handleQRCodeEvent.[wxEventPushBean]  添加团队  医生扫描");
                // 添加团队  医生扫描
                DtrdEntRdDoctor doctorInfo = getDoctorByUnionidOrOaOpenid(unionid, null);
                if (doctorInfo == null) {
                    // 未找到扫描id的医生记录
                    DtrdEntRdPatient patient = patientService.getPatientInfoByUnionId(unionid);
                    if (patient == null) {
                        // 没有患者记录，创建医生记录
                        doctorInfo = createDoctorByOaOpenidAndUnionid(openId, unionid);
                    } else {
                        log.info("DtrdEntRdDoctorServiceImpl.handleQRCodeEvent.[wxEventPushBean] 患者扫描医生添加团队二维码 ");
                        // 患者扫描医生添加团队二维码
                        String content = "您不可加入医生团队";
                        return JaxbUtil.converTomXml(resp.buildText(WechatConstant.MsgType.text, content));
                    }
                }
                // 绑定标签
                wechatApi.bindingTag(WechatConstant.OfficialAccountTag.DOCTOR_TAG_ID.getTag(), WechatConstant.OfficialAccountTag.getMutexTagIdList(WechatConstant.OfficialAccountTag.DOCTOR_TAG_ID.getTag()), openId);
                scanDoctorId = doctorInfo.getDataId();
                scanDoctorName = doctorInfo.getDoctorsName();
                // 加入团队
                // 更新医生团队信息
                if (Objects.equals(doctorId, scanDoctorId)) {
                    log.info("DtrdEntRdDoctorServiceImpl.handleQRCodeEvent: 管理者无须加入自己的团队");
                    return "";
                }
                doctorTeamDoctorService.saveDoctorTeamRelation(doctorId, scanDoctorId);
                log.info("DtrdEntRdDoctorServiceImpl.handleQRCodeEvent: 医生: {} 添加团队成功, 团队管理者id: {}", scanDoctorId, doctorId);
                // 不要出现 XX医生医生工作室 !
                doctorName = doctorName.endsWith("医生") ? doctorName.substring(0, doctorName.length() - 2) : doctorName;
                String content = "欢迎加入" + doctorName + "医生工作室!";
                return JaxbUtil.converTomXml(resp.buildText(WechatConstant.MsgType.text, content));
            } else {
                log.info("DtrdEntRdDoctorServiceImpl.handleQRCodeEvent.[wxEventPushBean] 患者扫描医生");
                // 患者扫描医生二维码
                DtrdEntRdPatient patient = patientService.getPatientInfoByUnionId(unionid);
                if (patient == null) {
                    DoctorInfo doctorInfo = getDoctorByUnionid(unionid);
                    log.info("DtrdEntRdDoctorServiceImpl.handleQRCodeEvent.[wxEventPushBean] doctorInfo=" + doctorInfo);
                    if (doctorInfo == null) {
                        log.info("DtrdEntRdDoctorServiceImpl.handleQRCodeEvent.[wxEventPushBean] 创建患者");
                        // 扫描患者不存在 ，创建患者记录
                        patient = patientService.createPatientByOpenIdAndUnionid(openId, unionid);
                        scanPatientId = patient.getDataId();
                        scanPatientName = patient.getPatientsName();
                    } else {
                        log.info("DtrdEntRdDoctorServiceImpl.handleQRCodeEvent.[wxEventPushBean]  unionid 已注册医生 ， 无法作为患者扫描添加");
                        // unionid 已注册医生 ， 无法作为患者扫描添加
                        String content = "二维码扫描错误，请重新扫描";
                        return JaxbUtil.converTomXml(resp.buildText(WechatConstant.MsgType.text, content));
                    }
                } else {
                    scanPatientId = patient.getDataId();
                    scanPatientName = patient.getPatientsName();
                }
                // 绑定标签
                WechatResponse wechatResponse = wechatApi.bindingTag(OfficialAccountTag.USER_TAG_ID.getTag(), WechatConstant.OfficialAccountTag.getMutexTagIdList(OfficialAccountTag.USER_TAG_ID.getTag()), openId);
                log.info("DtrdEntRdDoctorServiceImpl.handleQRCodeEvent.[wxEventPushBean] binding espone = " + wechatResponse);
                // 处理医患关系
                if (patient.getDoctorId() == null) {
                    // 当前未关注医生
                    doctorPatientRlService.saveOrUpdateDoctorPatientRelation(doctorId, scanPatientId, DoctorPatientRelationType.ADD_BY_PATIENT_SCAN.getType());
                    patient.setDoctorId(doctorId);
                    patientService.updateById(patient);
                }
                // 处理微信模板消息
                if (Objects.equals(patient.getDoctorId(), doctorId)) {
                    // 发送给医生  患者加入成功消息
                    String chatroomIdByPatientId = doctorPatientRlService.getChatroomIdByPatientId(scanPatientId, doctorId);
                    wechatApi.sendPatientRegisterMsg(scanPatientName, DateUtils.formatDate(DateUtils.datetime_sdf_wz.get().toPattern()), null, PathUtil.getChatroomUrl(USER_CATEGORY.USER_DOCTOR.getUser(), doctorId + "", chatroomIdByPatientId), doctor.getWxOaOpenid());
                    // 发送给扫码患者 绑定医生成功通知
                    log.info("DtrdEntRdDoctorServiceImpl.handleQRCodeEvent.[wxEventPushBean] scanPatientId =" + scanPatientId + "; doctorId=" + doctorId + "; chatRoomId=" + chatroomIdByPatientId);
                    wechatApi.sendBindDoctorMsg(doctorName, PathUtil.getChatroomUrl(USER_CATEGORY.USER_PATIENT.getUser(), scanPatientId + "", chatroomIdByPatientId), openId);
                    // 发送自定义消息 处理返回微信消息
                    String content = "欢迎加入毅瑭科技！请完善您的个人资料，让医生更好地为您提供个性化控糖指导。\n" +
                            "️<a href=\"" + PathUtil.getH5Domain() + "/fileSetting/index.html\"> \uD83C\uDF1F完善个人信息，点此填写</a>\n\n" +
                            "➡️<a data-miniprogram-appid=\"" + WechatUtil.getClientId() + "\" data-miniprogram-path=\"pages/serviceDetail/serviceDetail?packageid=1\"> 购买最新款智能血糖仪，只要299！点此购买或以旧换新</a>\n" +
                            "➡️<a href=\"" + PathUtil.getH5Domain() + "/patient/qrcode.html?userid=" + patient.getDataId() + "\"> 我的二维码，点此查看</a>\n" +
                            "➡️<a data-miniprogram-appid=\"" + WechatUtil.getClientId() + "\" data-miniprogram-path=\"pages/scan/scan\"> ️我的血糖仪，点此绑定</a>\n" +
                            "➡️<a data-miniprogram-appid=\"" + WechatUtil.getClientId() + "\" data-miniprogram-path=\"pages/index/index\"> ️我的医生，点此绑定</a>\n";
                    return JaxbUtil.converTomXml(resp.buildText(WechatConstant.MsgType.text, content));
                } else {
                    String content = "已关注其他医生，请勿重复关联";
                    return JaxbUtil.converTomXml(resp.buildText(WechatConstant.MsgType.text, content));
                }
            }
        }
    }

    @Override
    public boolean isInValidMobile(Integer doctorId, String mobile) {
        LambdaQueryWrapper<DtrdEntRdDoctor> queryWrapper = Wrappers.lambdaQuery(DtrdEntRdDoctor.class)
                .eq(DtrdEntRdDoctor::getDoctorsMobile, mobile);
        DtrdEntRdDoctor queryDoctor = this.getOne(queryWrapper);
        // 手机号码要么没有要么是自己的
        return queryDoctor != null && !Objects.equals(queryDoctor.getDataId(), doctorId);
    }

    @Override
    public boolean isValidDoctorId(Integer doctorId) {
        DtrdEntRdDoctor doctor = getById(doctorId);
        return Optional.ofNullable(doctor).isPresent();
    }

    @Override
    public Integer synchOrSaveDoctorInfoByPhone(Integer doctorId, String mobile) {
        LambdaQueryWrapper<DtrdEntRdDoctor> wrapper = Wrappers.lambdaQuery(DtrdEntRdDoctor.class)
                .eq(DtrdEntRdDoctor::getDoctorsMobile, mobile);
        DtrdEntRdDoctor phoneMaster = getOne(wrapper);
        Integer id;
        DtrdEntRdDoctor queryDoctor = getById(doctorId);
        // 查到的拥有 phone 的 doctor 的 id 和传入的 doctorId 不想等
        if (phoneMaster != null && !Objects.equals(phoneMaster.getDataId(), doctorId)) {
            // 更新 unionid 和 openid
            phoneMaster.setWxUnionid(queryDoctor.getWxUnionid());
            phoneMaster.setWxOaOpenid(queryDoctor.getWxOaOpenid());
            updateById(phoneMaster);
            // 删掉原来的id
            removeById(doctorId);
            id = phoneMaster.getDataId();
        } else {
            // 没有该手机号更新 doctorId 的医生字段
            queryDoctor.setDoctorsMobile(mobile);
            updateById(queryDoctor);
            id = doctorId;
        }
        return id;
    }

    @Override
    public Integer getLoginInDoctorId() {
        LoginUser loginUser = ShiroUtil.getLoginUser();
        if (loginUser != null) {
            String phone = loginUser.getPhone();
            LambdaQueryWrapper<DtrdEntRdDoctor> queryWrapper = Wrappers.lambdaQuery(DtrdEntRdDoctor.class)
                    .eq(DtrdEntRdDoctor::getDoctorsMobile, phone);
            DtrdEntRdDoctor queryDoctor = this.getOne(queryWrapper);
            if (queryDoctor != null) {
                return queryDoctor.getDataId();
            }
        }
        return null;
    }

    @Override
    public DoctorInfo getDoctorInfoByMobile(String mobile) {
        DtrdEntRdDoctor record = getDoctorPoRecordByPhone(mobile);
        return Optional.ofNullable(record).map(po -> new DoctorInfo().parseFromPO(po)).orElse(null);
    }

    @Override
    public DoctorInfo getDoctor(DoctorInfoRequest request) {
        LambdaQueryWrapper<DtrdEntRdDoctor> queryWrapper = baseQueryWrapper();
        Integer doctorId = request.getDoctorId();
        if (doctorId != null) {
            queryWrapper.eq(DtrdEntRdDoctor::getDataId, doctorId);
        }
        String mobile = request.getMobile();
        if (StrUtil.isNotBlank(mobile)) {
            queryWrapper.eq(DtrdEntRdDoctor::getDoctorsMobile, mobile);
        }
        return wrapperDoctorInfo(queryWrapper);
    }

    @Override
    public DoctorInfo getDoctor(String phone) {
        LambdaQueryWrapper<DtrdEntRdDoctor> queryWrapper = baseQueryWrapper()
                .eq(DtrdEntRdDoctor::getDoctorsMobile, phone);
        return wrapperDoctorInfo(queryWrapper);
    }

    /**
     * 根据手机号码查询医生表记录
     *
     * @param phone
     * @return
     */
    @DS("multi-datasource1")
    private DtrdEntRdDoctor getDoctorPoRecordByPhone(String phone) {
//        LambdaQueryWrapper<DtrdEntRdDoctor> last = baseQueryWrapper().eq(DtrdEntRdDoctor::getDoctorsMobile, phone).last("limit 1");
        return baseMapper.getDoctorPoRecordByPhone(phone);
    }

    @Override
    public DoctorInfo getDoctorByUnionid(String unionid) {
        LambdaQueryWrapper<DtrdEntRdDoctor> wrapper = baseQueryWrapper()
                .eq(DtrdEntRdDoctor::getWxUnionid, unionid)
                .last(" limit 1");
        return wrapperDoctorInfo(wrapper);
    }

    @Override
    public DtrdEntRdDoctor getDoctorByUnionidOrOaOpenid(String unionid, String oAOpenid) {
        return baseMapper.getDoctorByUnionidOpenId(unionid, oAOpenid);
    }

    @Override
    public DtrdEntRdDoctor createDoctorByOaOpenidAndUnionid(String openid, String unionid) {
        DtrdEntRdDoctor newDoctor = new DtrdEntRdDoctor().init();
        newDoctor.setWxUnionid(unionid);
        newDoctor.setWxOaOpenid(openid);
        save(newDoctor);
        return newDoctor;
    }

    @Override
    public boolean saveOrUpdateDoctor(DoctorInfo doctorInfo) {
        DtrdEntRdDoctor doctor = new DtrdEntRdDoctor();
        boolean result;
        if (doctorInfo.getDataId() == null) {
            doctor = doctor.init();
            doctor = doctor.parseFromDTO(doctorInfo);
            result = save(doctor);
        } else {
            result = updateDoctor(doctorInfo, doctor);
        }
        Integer newDoctorId = doctor.getDataId();
        // 查询该医生是否有团队, 没有才生成团队, 这里就不进行团队的更新了
        if (doctorInfo.getDoctorsType() != null && doctorInfo.getDoctorsType() == DEPARTMENT_DOCTOR.getType()
                && !doctorTeamService.hasDoctorTeam(newDoctorId)) {
            DtrdEntRdDoctorTeam newDoctorTeam = new DtrdEntRdDoctorTeam().init();
            newDoctorTeam.setName(doctorInfo.getDoctorsName() + "的团队");
            newDoctorTeam.setDescription(doctorInfo.getDoctorsName() + "的团队");
            newDoctorTeam.setManageDoctorId(newDoctorId);
            doctorTeamService.save(newDoctorTeam);
        }
        return result;
    }

    private Boolean updateDoctor(DoctorInfo doctorInfo, DtrdEntRdDoctor doctor) {
        doctor = doctor.parseFromDTO(doctorInfo);
        log.info("doctor:" + doctor);
        // 查询医生信息
        DtrdEntRdDoctor doctorData = getById(doctorInfo.getDataId());

        if (Optional.ofNullable(doctorData.getDoctorsIsverify()).orElse(DoctorVerifyState.VERIFY_FAILURE.getState()) == DoctorVerifyState.VERIFY_FAILURE.getState()) {
            // 当前是认证失败  修改资料时直接设为认证中
            doctor.setDoctorsIsverify(DoctorVerifyState.VERIFING.getState());
        } else if (Optional.ofNullable(doctorInfo.getDoctorsIsverify()).orElse(DoctorVerifyState.TO_VERIFY.getState()) == DoctorVerifyState.TO_VERIFY.getState() ||
                // 四证修改、重置审核状态
                !Objects.equals(doctorInfo.getDoctorsWorkCard(), doctorData.getDoctorsWorkCard()) ||
                !Objects.equals(doctorInfo.getDoctorsProfessionImg(), doctorData.getDoctorsProfessionImg()) ||
                !Objects.equals(doctorInfo.getDoctorsCertificate(), doctorData.getDoctorsCertificate()) ||
                !Objects.equals(doctorInfo.getDoctorsWorkPermits(), doctorData.getDoctorsWorkPermits())
        ) {
            log.info("DtrdEntRdDoctorServiceImpl.updateDoctor.[doctorInfo, doctor] 修改四证 重置为认证中 \n(Objects.equals(doctorInfo.getDoctorsWorkCard(), doctorData.getDoctorsWorkCard()))=" + (Objects.equals(doctorInfo.getDoctorsWorkCard(), doctorData.getDoctorsWorkCard()))
                    + "(Objects.equals(doctorInfo.getDoctorsProfessionImg(), doctorData.getDoctorsProfessionImg()))=" + (Objects.equals(doctorInfo.getDoctorsProfessionImg(), doctorData.getDoctorsProfessionImg()))
                    + "(Objects.equals(doctorInfo.getDoctorsCertificate(), doctorData.getDoctorsCertificate()))=" + (Objects.equals(doctorInfo.getDoctorsCertificate(), doctorData.getDoctorsCertificate()))
                    + "(Objects.equals(doctorInfo.getDoctorsWorkPermits(), doctorData.getDoctorsWorkPermits())=" + (Objects.equals(doctorInfo.getDoctorsWorkPermits(), doctorData.getDoctorsWorkPermits()))
            );
            doctor.setDoctorsIsverify(DoctorVerifyState.VERIFING.getState());
        }

        // 保存 doctor 表
        boolean result = saveOrUpdate(doctor);
        if (result && doctorInfo.getDoctorsIsverify() != null) {
            log.info("DtrdEntRdDoctorServiceImpl.updateDoctor.[doctorInfo, doctor] ");
            if (!Objects.equals(doctor.getDoctorsIsverify(), doctorInfo.getDoctorsIsverify()) &&
                    doctorInfo.getDoctorsIsverify() != DoctorVerifyState.VERIFING.getState()) {
                boolean setVerify = this.setDoctorIsverify(doctorInfo.getDataId(), doctorInfo.getDoctorsIsverify(), doctorInfo.getRemark());
                if (!setVerify) {
                    result = false;
                }
            }
        }
        return result;
    }

    @Override
    public boolean saveDoctorByBackstage(DoctorInfo doctorTotalInfo) {
        DtrdEntRdDoctor po = new DtrdEntRdDoctor();
        if (doctorTotalInfo.getDataId() == null) {
            po = po.init();
        }
        po = po.parseFromDTO(doctorTotalInfo);
        // 设置钱包密码加密
        po.setDoctorsWalletPassword(StringUtil.Md5(doctorTotalInfo.getDoctorsWalletPassword()));
        return saveOrUpdate(po);
    }

    @Override
    public boolean verifyWallyPwd(String walletPwd, Integer doctorId) {
        DtrdEntRdDoctor queryDoctor = this.getById(doctorId);
        if (queryDoctor == null) {
            return false;
        }
        String queryPwd = queryDoctor.getDoctorsWalletPassword();
        String pwd = StringUtil.Md5(walletPwd);
        return queryPwd.equals(pwd);
    }

    @Override
    public List<OrganizationListInfo> getDoctorRlOrganization(Integer doctorId) {
        List<String> orgCodes = doctorOrgRlService.getDoctorRlOrgCode(doctorId);
        if (CollectionUtil.isEmpty(orgCodes)) {
            return null;
        }
        LambdaQueryWrapper<DtrdEntRdOrganization> queryWrapper = Wrappers.lambdaQuery(DtrdEntRdOrganization.class)
                .in(DtrdEntRdOrganization::getOrganizationCode, orgCodes);
        List<DtrdEntRdOrganization> organizationPoList = organizationService.list(queryWrapper);
        List<OrganizationListInfo> organizationDetails = new ArrayList<>(organizationPoList.size());
        if (CollectionUtil.isNotEmpty(organizationPoList)) {
            organizationDetails = organizationPoList.stream()
                    .map(po -> {
                        OrganizationListInfo organizationListInfo = new OrganizationListInfo(po);
                        StringJoiner joiner = new StringJoiner("");
                        if (po.getOrganizationProvinceId() != null) {
                            String province = districtInfoService.getDistrictNameByAreaId(po.getOrganizationProvinceId());
                            joiner.add(province);
                        }
                        if (po.getOrganizationCityId() != null) {
                            String city = districtInfoService.getDistrictNameByAreaId(po.getOrganizationCityId());
                            joiner.add(city);
                        }
                        if (po.getOrganizationAreaId() != null) {
                            String area = districtInfoService.getDistrictNameByAreaId(po.getOrganizationAreaId());
                            joiner.add(area);
                        }
                        organizationListInfo.setOrganizationAddress(joiner.toString());
                        return organizationListInfo;
                    })
                    .collect(Collectors.toList());
        }
        return organizationDetails;
    }

    @Override
    public boolean addDoctorPatientRelation(Integer doctorId, Integer patientId) {
        // 设置 patient 表的 doctorId 字段
        DtrdEntRdPatient queryPatient = patientService.getById(patientId);
        if (queryPatient == null) {
            return false;
        }
        queryPatient.setDoctorId(doctorId);
        boolean result1 = patientService.updateById(queryPatient);
        DtrdEntRdDoctor queryDoctor = getById(doctorId);
        if (queryDoctor == null) {
            return false;
        }
        // doctorPatientRelation, 存 dtrd_rl_doctor_patient 表
        DtrdRlDoctorPatient dpRl = new DtrdRlDoctorPatient().init();
        dpRl.setDoctorId(doctorId);
        dpRl.setPatientId(patientId);
        dpRl.setDoctorType(queryDoctor.getDoctorsType());
        // 默认为未分组
        dpRl.setGroupId(NO_GROUP.getType());
        dpRl.setChatRoomId(IdWorker.get32UUID());
        boolean result2 = doctorPatientRlService.save(dpRl);
        return result1 && result2;
    }

    @Override
    public List<PatientInfo> searchPatient(Integer doctorId, SearchPatientRequest request) {
        LambdaQueryWrapper<DtrdEntRdPatient> patientQuery = Wrappers.lambdaQuery(DtrdEntRdPatient.class)
                .eq(DtrdEntRdPatient::getDoctorId, doctorId);
        String mobile = request.getMobile();
        if (StrUtil.isNotBlank(mobile)) {
            patientQuery.like(DtrdEntRdPatient::getPatientsMobile, StringUtil.fuzzySearchWrapper(mobile));
        }
        String name = request.getName();
        if (StrUtil.isNotBlank(name)) {
            patientQuery.like(DtrdEntRdPatient::getPatientsName, StringUtil.fuzzySearchWrapper(name));
        }
        List<DtrdEntRdPatient> list = patientService.list(patientQuery);
        List<PatientInfo> infos = new ArrayList<>(list.size());
        if (CollectionUtil.isNotEmpty(list)) {
            infos = list.stream()
                    .map(po -> new PatientInfo().parseFromPO(po))
                    .collect(Collectors.toList());
        }
        return infos;
    }

    @Override
    public String getDoctorName(Integer doctorId) {
        DtrdEntRdDoctor doctor = this.getById(doctorId);
        return doctor != null ? doctor.getDoctorsName() : null;
    }

    @Override
    public String getDoctorTeamName(Integer doctorId) {
        String doctorName = getDoctorName(doctorId);
        if (StrUtil.isNotBlank(doctorName)) {
            if (doctorName.endsWith("医生")) {
                return doctorName + "工作室";
            } else {
                return doctorName + "医生工作室";
            }
        }
        return null;
    }

    @Override
    public IPage<DoctorPatientInfo> pageGroupPatient(Integer doctorId, Integer groupId, Integer page, Integer pageSize) {
        LambdaQueryWrapper<DtrdRlGroupPatient> groupPatientQueryWrapper = Wrappers.lambdaQuery(DtrdRlGroupPatient.class)
                .eq(DtrdRlGroupPatient::getGroupId, groupId);
        List<DtrdRlGroupPatient> groupPatientList = groupPatientService.list(groupPatientQueryWrapper);
        if (CollectionUtil.isEmpty(groupPatientList)) {
            return null;
        }
        List<Integer> groupPatientIds = groupPatientList.stream()
                .map(DtrdRlGroupPatient::getPatientId)
                .collect(Collectors.toList());
        LambdaQueryWrapper<DtrdEntRdPatient> patientQuery = Wrappers.lambdaQuery(DtrdEntRdPatient.class)
                .eq(DtrdEntRdPatient::getDoctorId, doctorId)
                .in(DtrdEntRdPatient::getDataId, groupPatientIds);
        Page<DtrdEntRdPatient> queryPage = new Page<>(page, pageSize);
        queryPage = patientService.page(queryPage, patientQuery);
        return queryPage.convert(po -> {
            DoctorPatientInfo info = new DoctorPatientInfo(po);
            // 设置起始时间
            String time = packagePatientService.getPatientInfoStartTime(po.getDataId(), Constant.PackageServiceStatus.SERVICING.getType());
            if (StrUtil.isNotBlank(time)) {
                info.setStartTime(time);
            }
            return info;
        });
    }

    @Override
    public List<Integer> listPatientIds(Integer doctorId) {
        LambdaQueryWrapper<DtrdEntRdPatient> queryWrapper = Wrappers.lambdaQuery(DtrdEntRdPatient.class)
                .eq(DtrdEntRdPatient::getDoctorId, doctorId);
        List<DtrdEntRdPatient> patients = patientService.list(queryWrapper);
        return Optional.ofNullable(patients)
                .map(list -> list.stream().map(DtrdEntRdPatient::getDataId).collect(Collectors.toList()))
                .orElse(null);
    }

    @Override
    public IPage<DoctorPatientInfo> pagePackagePatient(Integer doctorId, Integer status, Integer page, Integer pageSize) {
        // 查询医生关联的患者， 没有关联患者直接返回
        List<Integer> patientIds = this.listPatientIds(doctorId);
        if (CollectionUtil.isEmpty(patientIds)) {
            return null;
        }
        // TODO 这个先固定体验式服务包的 packageId == 1
        int packageId = 1;
        LambdaQueryWrapper<DtrdRlPackagePatient> packagePatientQuery = Wrappers.lambdaQuery(DtrdRlPackagePatient.class)
                .eq(DtrdRlPackagePatient::getStatus, status)
                .eq(DtrdRlPackagePatient::getPackageId, packageId)
                .in(DtrdRlPackagePatient::getPatientId, patientIds);
        // 查询 patient 和 服务包 的关联，如果为没有记录返回null
        List<DtrdRlPackagePatient> packagePatientList = packagePatientService.list(packagePatientQuery);
        if (CollectionUtil.isEmpty(packagePatientList)) {
            return null;
        }
        List<Integer> packagePatientIds = packagePatientList.stream()
                .map(DtrdRlPackagePatient::getPatientId)
                .collect(Collectors.toList());
        Page<DtrdEntRdPatient> queryPage = new Page<>(page, pageSize);
        LambdaQueryWrapper<DtrdEntRdPatient> queryWrapper = Wrappers.lambdaQuery(DtrdEntRdPatient.class)
                .in(DtrdEntRdPatient::getDataId, packagePatientIds);
        queryPage = patientService.page(queryPage, queryWrapper);
        return queryPage.convert(po -> {
            DoctorPatientInfo info = new DoctorPatientInfo(po);
            // 设置起始时间
            String time = packagePatientService.getPatientInfoStartTime(po.getDataId(), status);
            if (StrUtil.isNotBlank(time)) {
                info.setStartTime(time);
            }
            return info;
        });
    }

    @Override
    public DoctorAchievement getDoctorAchievement(Integer doctorId) {
        DoctorAchievement achievement = new DoctorAchievement();
        // 患者
        LambdaQueryWrapper<DtrdRlDoctorPatient> queryWrapper1 = Wrappers.lambdaQuery(DtrdRlDoctorPatient.class)
                .eq(DtrdRlDoctorPatient::getDoctorId, doctorId);
        List<DtrdRlDoctorPatient> doctorPatientList = doctorPatientRlService.list(queryWrapper1);
        long inManageNum = 0L;
        long continueManageNum = 0L;
        if (CollectionUtil.isNotEmpty(doctorPatientList)) {
            inManageNum = doctorPatientList.stream()
                    .filter(record -> record.getGroupId().equals(Constant.Group.IN_MANAGE.getType()))
                    .count();
            continueManageNum = doctorPatientList.stream()
                    .filter(record -> record.getGroupId().equals(Constant.Group.CONTINUE_MANAGE.getType()))
                    .count();
        }
        // 服务包
        // TODO 体验式服务包的id暂定为1
        int packageNum = packagePatientService.countDoctorPatientPackage(doctorId, 1);
        // 本周预约
        List<Date> weekDate = DateUtils.getWeekDate(new Date());
        int weeklyPatientCount = flupAppointmentRecordService.countPatientWeekly(doctorId, weekDate.get(0), weekDate.get(6));
        // 设置医生信息
        DtrdEntRdDoctor doctor = getById(doctorId);
        achievement.parseFromPo(doctor);
        // 设置返回参数
        achievement.setPatientTotal(doctorPatientList.size());
        achievement.setPatientInManage(inManageNum);
        achievement.setPatientContinueManage(continueManageNum);
        achievement.setPackageTotal(packageNum);
        achievement.setAppointmentNumWeekly(weeklyPatientCount);
        return achievement;
    }

    @Override
    public boolean checkDoctorMobile(String mobile, Integer doctorId) {
        LambdaQueryWrapper<DtrdEntRdDoctor> wrapper = Wrappers.lambdaQuery(DtrdEntRdDoctor.class)
                .eq(DtrdEntRdDoctor::getDoctorsMobile, mobile);
        DtrdEntRdDoctor doctor = getOne(wrapper);
        return doctor == null || doctor.getDataId().equals(doctorId);
    }

    @Override
    public boolean hasDoctorMobile(String mobile) {
        LambdaQueryWrapper<DtrdEntRdDoctor> wrapper = Wrappers.lambdaQuery(DtrdEntRdDoctor.class)
                .eq(DtrdEntRdDoctor::getDoctorsMobile, mobile);
        DtrdEntRdDoctor queryDoctor = getOne(wrapper);
        return queryDoctor != null;
    }

    @Override
    public DoctorInfo createDoctorByOaOpenid(String openid) {
        DtrdEntRdDoctor newDoctor = new DtrdEntRdDoctor().init();
        newDoctor.setWxOaOpenid(openid);
        save(newDoctor);
        return new DoctorInfo().parseFromPO(newDoctor);
    }

    @Override
    public DoctorInfo createDoctorByWechatUserInfo(WechatOfficialAccountUserInfo userInfo) {
        DtrdEntRdDoctor newDoctor = new DtrdEntRdDoctor().init();
        newDoctor = newDoctor.parseFromDTO(userInfo);
        save(newDoctor);
        return new DoctorInfo().parseFromPO(newDoctor);
    }

    @Override
    public void updateDoctorInfoByWechatUserInfo(WechatOfficialAccountUserInfo userInfo, Integer did) {
        DtrdEntRdDoctor doctor = getById(did);
        if (StrUtil.isBlank(doctor.getDoctorsName())) {
            doctor.setDoctorsName(userInfo.getNickname());
        }
        if (StrUtil.isBlank(doctor.getDoctorsImg())) {
            doctor.setDoctorsImg(userInfo.getHeadimgurl());
        }
        if (doctor.getWxOaOpenid() == null) {
            doctor.setWxOaOpenid(userInfo.getOpenid());
        }
        if (doctor.getWxUnionid() == null) {
            doctor.setWxUnionid(userInfo.getUnionid());
        }
        if (doctor.getDoctorsSex() == null) {
            doctor.setDoctorsSex(userInfo.getSex());
        }
        if (doctor.getDoctorsType() != null && doctor.getDoctorsType().equals(Constant.Executor.DOCTOR.getType())) {
            // 更新医生团队
            DtrdEntRdDoctorTeam team = doctorTeamService.getDoctorTeamByDoctorId(did);
            if (team == null) {
                doctorTeamService.createDoctorTeamByDoctorId(did);
            }
            // 更新二维码
//            WechatQrCodeTicket addPatientQrCodeTicket = wechatApi.createPermanentQrCode(did + "", did + "," + DoctorQrCodeType.ADD_PATIENT.getType());
//            String addPatientQrCode = addPatientQrCodeTicket != null ? addPatientQrCodeTicket.getQrCodeUrl() : null;
//            if (StrUtil.isNotBlank(addPatientQrCode)) {
//                log.info("DtrdEntRdDoctorServiceImpl.updateDoctorInfoByWechatUserInfo, 添加患者二维码: {}", addPatientQrCode);
//                doctor.setQrcodeAddPatient(addPatientQrCode);
//                doctor.setWxOaQrcodeSourceUrl(addPatientQrCodeTicket.getUrl());
//            }
//            WechatQrCodeTicket addTeamQrcodeTicket = wechatApi.createPermanentQrCode(did + "", did + "," + DoctorQrCodeType.ADD_TEAM.getType());
//            String addTeamQrCode = addTeamQrcodeTicket != null ? addTeamQrcodeTicket.getQrCodeUrl() : null;
//            if (StrUtil.isNotBlank(addTeamQrCode)) {
//                log.info("DtrdEntRdDoctorServiceImpl.updateDoctorInfoByWechatUserInfo, 添加医生团队二维码: {}", addPatientQrCode);
//                doctor.setQrcodeAddTeam(addTeamQrCode);
//            }
        }
        updateById(doctor);
    }

    @Override
    public List<DoctorInfo> getExceptTeamDoctor(String doctorName, Integer teamId) {
        LambdaQueryWrapper<DtrdEntRdDoctor> wrapper = Wrappers.lambdaQuery(DtrdEntRdDoctor.class)
                .like(DtrdEntRdDoctor::getDoctorsName, StringUtil.fuzzySearchWrapper(doctorName));
        List<DtrdEntRdDoctor> doctors = list(wrapper);
        // 如果有传入 teamId 则排除此团队 id 里的医生
        if (teamId != null) {
            List<Integer> teamDoctorIds = doctorTeamService.getTeamDoctorIds(teamId);
            doctors = excludeDoctor(teamDoctorIds, doctors);
        }
        if (CollectionUtil.isNotEmpty(doctors)) {
            return doctors.stream().map(p -> new DoctorInfo().parseFromPO(p)).collect(Collectors.toList());
        }
        return null;
    }

    @Override
    public DtrdEntRdDoctor getOrCreateDoctor(String doctorName, String doctorPhone, Integer doctorType) {
        LambdaQueryWrapper<DtrdEntRdDoctor> wrapper = Wrappers.lambdaQuery(DtrdEntRdDoctor.class)
                .eq(DtrdEntRdDoctor::getDoctorsName, doctorName)
                .eq(DtrdEntRdDoctor::getDoctorsMobile, doctorPhone);
        // .eq(DtrdEntRdDoctor::getDoctorsType, doctorType); //暂定取消角色判断
        DtrdEntRdDoctor doctor = getOne(wrapper);
        if (doctor == null) {
            if (hasDoctorMobile(doctorPhone)) {
                throw new JeecgBootException("手机号重复");
            }
            doctor = new DtrdEntRdDoctor(doctorPhone, doctorName, doctorType);
            save(doctor);
        }
        return doctor;
    }

    @Override
    public boolean updateTeamDoctorInfo(UpdateTeamDoctorRequest request) {
        DtrdEntRdDoctor doctor = getById(request.getDoctorId());
        doctor = doctor.parseFromDTO(request);
        return updateById(doctor);
    }

    /**
     * 排除 doctors 的 id 在 doctorIds 里的医生
     */
    private List<DtrdEntRdDoctor> excludeDoctor(List<Integer> doctorIds, List<DtrdEntRdDoctor> doctors) {
        if (CollectionUtil.isNotEmpty(doctors) && CollectionUtil.isNotEmpty(doctorIds)) {
            return doctors.stream()
                    .filter(p -> !doctorIds.contains(p.getDataId()))
                    .collect(Collectors.toList());
        }
        return doctors;
    }

    private LambdaQueryWrapper<DtrdEntRdDoctor> baseQueryWrapper() {
        return Wrappers.lambdaQuery(DtrdEntRdDoctor.class).eq(DtrdEntRdDoctor::getIsDel, 0);
    }

    /**
     * 包装返回数据
     *
     * @return 包装后的返回对象
     */
    private DoctorInfo wrapperDoctorInfo(LambdaQueryWrapper<DtrdEntRdDoctor> wrapper) {
        DtrdEntRdDoctor doctor = getOne(wrapper, false);
        log.info("DtrdEntRdDoctorServiceImpl.wrapperDoctorInfo.[wrapper] doctor=" + doctor);
        return Optional.ofNullable(doctor)
                .map(po -> {
                    DoctorInfo info = new DoctorInfo().parseFromPO(po);
                    StringBuilder workPlace = new StringBuilder();
                    // 市
                    if (po.getDoctorsCityId() != null && !Objects.equals(po.getDoctorsCityId(), po.getDoctorsProvinceId())) {
                        String city = districtInfoService.getDistrictNameById(po.getDoctorsCityId());
                        workPlace.append(city);
                    }
                    info.setDoctorsCity(workPlace.toString());
                    return info;
                })
                .orElse(null);
    }

    @Override
    public boolean updateDoctorStatus(Integer doctorId, int status) {
        //根据doctorId取出医生
        DtrdEntRdDoctor doctor = getById(doctorId);
        if (doctor != null) {
            //判断状态栏中是否有状态信息，没有的话将状态直接写入
            if (doctor.getDoctorsStatus() == null || doctor.getDoctorsStatus() != status) {
                doctor.setDoctorsStatus(status);
            }
            return updateById(doctor);
        } else {
            return false;
        }
    }

    @Override
    public boolean setDoctorIsverify(Integer doctorId, int isverify, String failureReason) {
        log.info("DtrdEntRdDoctorServiceImpl.setDoctorIsverify.[doctorId, isverify, failureReason] isverify=" + isverify);
        //根据doctorId取出医生
        DtrdEntRdDoctor doctor = getById(doctorId);
        //判断医生认证信息
        boolean result = false;
        if (doctor != null) {
            if (isverify == DoctorVerifyState.VERIFY_SUCCESS.getState()) {
                doctor.setDoctorsIsverify(isverify);
            } else if (isverify == DoctorVerifyState.VERIFY_FAILURE.getState()) {
                doctor.setDoctorsIsverify(DoctorVerifyState.VERIFY_FAILURE.getState());
            } else {
                doctor.setDoctorsIsverify(DoctorVerifyState.VERIFING.getState());
            }

            doctor.setRemark(failureReason);
            doctor.setDoctorsVerifyTime(DateUtils.formatTime(new Date()));
            result = updateById(doctor);
//            if (isverify == DoctorVerifyState.VERIFY_SUCCESS.getState()) {
//                sendQrCodeGenerateEvent(doctor);
//            }
        }
        // 增加微信公众号审核消息推送 肖 2022-05-28 12:37:29
        String openid = doctor.getWxOaOpenid();
        if (StrUtil.isNotBlank(openid)) {
            String msgTitle = "";
            String url;
            if (isverify == DoctorVerifyState.VERIFY_SUCCESS.getState() || isverify == DoctorVerifyState.VERIFY_FAILURE.getState()) {
                if (isverify == DoctorVerifyState.VERIFY_SUCCESS.getState()) {
                    url = PathUtil.getH5Domain() + "/doctor/doctorStudio.html?did=" + doctorId;
                    msgTitle = "审核通过：恭喜您成功通过认证审核！";
                } else {
                    url = null;
                    msgTitle = "审核不通过：您的认证审核未能通过";
                }
                wechatApi.sendAccountAuditMsg(msgTitle, doctor.getDoctorsName(), null, doctor.getDoctorsMobile(), doctor.getDoctorsHospital(), null, failureReason, url, openid);
            }
        }
        return result;
    }

    @Override
    public IPage<DoctorInfo> listDoctorInfo(Integer pageNum, Integer pageSize, DoctorPageRequest request) {
        LambdaQueryWrapper<DtrdEntRdDoctor> queryWrapper = baseQueryWrapper();
        String doctorName = request.getDoctorsName();
        String orgCode = request.getOrgCode();
        if (StringUtils.isNotBlank(orgCode)) {
            queryWrapper.eq(DtrdEntRdDoctor::getDoctorsHospitalId, request.getOrgCode());
        }
        if (doctorName != null) {
            queryWrapper.like(DtrdEntRdDoctor::getDoctorsName, StringUtil.fuzzySearchWrapper(doctorName));
        }
        Boolean isDoctorAssistant = request.getIsDoctorAssistant();
        if (isDoctorAssistant != null && isDoctorAssistant) {
            List<Integer> list = new ArrayList<>();
            for (int i = 1; i <= 5; i++) {
                list.add(i);
            }
            queryWrapper.in(DtrdEntRdDoctor::getDoctorsType, list);
        }
        Integer doctorIsVerify = request.getDoctorsIsverify();
        if (doctorIsVerify != null) {
            queryWrapper.eq(DtrdEntRdDoctor::getDoctorsIsverify, doctorIsVerify);
        }
        String doctorMobile = request.getDoctorsMobile();
        if (doctorMobile != null) {
            queryWrapper.like(DtrdEntRdDoctor::getDoctorsMobile, StringUtil.fuzzySearchWrapper(doctorMobile));
        }
        queryWrapper.orderByDesc(DtrdEntRdDoctor::getUpdateTime);
        IPage<DtrdEntRdDoctor> page = new Page<>(pageNum, pageSize);
        page = this.page(page, queryWrapper);
        return page.convert(p -> new DoctorInfo(p));

    }

    @Override
    public List<Integer> listDoctorIdsByDoctorType(Integer... doctorTypes) {
        LambdaQueryWrapper<DtrdEntRdDoctor> wrapper = Wrappers.lambdaQuery(DtrdEntRdDoctor.class)
                .eq(DtrdEntRdDoctor::getIsDel, 0);
        if (doctorTypes != null) {
            wrapper.in(DtrdEntRdDoctor::getDoctorsType, doctorTypes);
        }
        List<DtrdEntRdDoctor> doctors = list(wrapper);
        if (CollectionUtil.isNotEmpty(doctors)) {
            return doctors.stream()
                    .map(DtrdEntRdDoctor::getDataId)
                    .collect(Collectors.toList());
        }
        return null;
    }

    @Override
    public DoctorIndexDynamicInfo getDoctorIndexDynamicInfo(Integer doctorId) {
        List<Integer> patientIds = doctorPatientRlService.listPatientIdsByDoctorId(doctorId);
        if (CollectionUtil.isNotEmpty(patientIds)) {
            DoctorIndexDynamicInfo dynamicInfo = sugarRecordService.listPatientSugarValuesInfo(patientIds);
//            List<BarChartItem> list = new ArrayList<>(4);
//            list.add(new BarChartItem("空腹血糖达标率", 25));
//            list.add(new BarChartItem("糖化达标率", 50));
//            list.add(new BarChartItem("BMI达标率", 75));
//            list.add(new BarChartItem("腰围达标率", 100));
//            dynamicInfo.setReachStandardRateBarChart(list);
            if (dynamicInfo != null) {
                PatientTargetReachStandardAvgRateDaily rateDaily = targetService.getPatientTargetReachStandardAvgRateDaily(patientIds);
                if (rateDaily != null) {
                    dynamicInfo = dynamicInfo.parseFromDTO(rateDaily);
                    log.info("医生端每日达标率: {}", dynamicInfo.toString());
                }
            }
            return dynamicInfo;
        }
        return null;
    }

    @Override
    public DoctorIndexDynamicInfo getDoctorIndexDynamicInfo(List<Integer> doctorIdList) {
        List<Integer> patientIds = doctorPatientRlService.listPatientIdsByDoctorId(doctorIdList);
        if (CollectionUtil.isNotEmpty(patientIds)) {
            DoctorIndexDynamicInfo dynamicInfo = sugarRecordService.listPatientSugarValuesInfo(patientIds);
//            List<BarChartItem> list = new ArrayList<>(4);
//            list.add(new BarChartItem("空腹血糖达标率", 25));
//            list.add(new BarChartItem("糖化达标率", 50));
//            list.add(new BarChartItem("BMI达标率", 75));
//            list.add(new BarChartItem("腰围达标率", 100));
//            dynamicInfo.setReachStandardRateBarChart(list);
            if (dynamicInfo != null) {
                PatientTargetReachStandardAvgRateDaily rateDaily = targetService.getPatientTargetReachStandardAvgRateDaily(patientIds);
                if (rateDaily != null) {
                    dynamicInfo = dynamicInfo.parseFromDTO(rateDaily);
                    log.info("医生端每日达标率: {}", dynamicInfo.toString());
                }
            }
            return dynamicInfo;
        }
        return null;
    }

    @Override
    public List<PatientServiceInfo> getDoctorService(List<Integer> doctorIdList, Integer packageId) {
        List<PatientServiceInfo> list = doctorPatientRlService.getPatientInfomationInDoctorService(doctorIdList, packageId);
        list.forEach(map ->
        {
            map.setPatientsDiabetisTypeName(Constant.DiabetesType.valueOf(map.getPatientsDiabetisType()).getName());
            if (map.getPatientsBirthday() != null) {
                map.setPatientsAge(DateUtil.ageOfNow(map.getPatientsBirthday()));
            }
        });
        return list;
    }

    @Override
    public String generateQrCode(Integer doctorId, Integer qrCodeType) {
        DtrdEntRdDoctor doctor = getById(doctorId);
        if (doctor == null) {
            return null;
        }
        WechatQrCodeTicket qrCodeTicket = wechatApi.createUserQrCode(doctor.getDataId(), qrCodeType, null);
        log.info("DtrdEntRdDoctorServiceImpl.sendQrCodeGenerateEvent.[doctorId] qrCodeTicket=" + qrCodeTicket);
        if (qrCodeTicket != null) {
            String qrCode = qrCodeTicket.getQrCodeUrl();
            if (qrCodeType == Constant.DoctorQrCodeType.ADD_PATIENT.getType()) {
                doctor.setQrcodeAddPatient(qrCode);
                doctor.setWxOaQrcodeSourceUrl(qrCodeTicket.getUrl());
            } else if (qrCodeType == DoctorQrCodeType.ADD_TEAM.getType()) {
                doctor.setQrcodeAddTeam(qrCode);
            }
            boolean b = updateById(doctor);
            log.info("DtrdEntRdDoctorServiceImpl.generateQrCode.[doctorId, qrCodeType] update result = " + b);
            return qrCode;
        } else {
            return null;
        }
    }

    @Override
    public DtrdEntRdDoctor getDoctorInfoByPatientId(Integer patientId) {
        return baseMapper.getDoctorInfoByPatientId(patientId);
    }

    @Override
    public DtrdEntRdDoctor getDoctorByQrcodeUrl(String qrcodeUrl) {
        return baseMapper.getDoctorByQrcodeUrl(qrcodeUrl);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteDoctorRecordById(List<Integer> doctorIds) {
        doctorTeamDoctorService.removeDoctorTeamRelation(doctorIds);
        return removeByIds(doctorIds);
    }

    @Override
    public List<DoctorInfo> getDoctorList(String orgCode, String doctorsName, String doctorsMobile) {
        List<DtrdEntRdDoctor> list = baseMapper.getDoctorList(orgCode, doctorsName, doctorsMobile);
        if (CollectionUtil.isNotEmpty(list)) {
            List<DoctorInfo> doctorList = new ArrayList<>(list.size());
            list.stream().map(DoctorInfo::new).forEach(doctorList::add);
            return doctorList;
        }
        return null;
    }

    @Override
    public List<DtrdEntRdDoctor> getDoctorInfoByDoctorIds(List<Integer> doctorIdList) {
        return baseMapper.getDoctorInfoByDoctorIds(doctorIdList);
    }

    @Override
    public List<DtrdEntRdDoctor> getDoctorByIdList(List<Integer> doctorIdList) {
        return list(baseQueryWrapper().in(DtrdEntRdDoctor::getDataId, doctorIdList));
    }

    @Override
    public String getDoctorOrgCodeById(Integer doctorId) {
        return baseMapper.getDoctorOrgCodeById(doctorId);
    }

    /**
     * 创建医生账号
     *
     * @param user
     * @param doctorType 医生类型ID
     */
    @DS("multi-datasource1")
    @Override
    public void registerDoctor(SysUser user, String doctorType) {
        log.info("DtrdEntRdDoctorServiceImpl.registerDoctor.[user, doctorType] baseMapper=" + baseMapper);
        DtrdEntRdDoctor recordByPhone = getDoctorPoRecordByPhone(user.getPhone());
        // 医生手机号码已存在 暂不处理
        if (recordByPhone == null) {
            recordByPhone = new DtrdEntRdDoctor().init();
            recordByPhone.setDoctorsIsverify(DoctorVerifyState.VERIFING.getState());
            recordByPhone.setDoctorsPassword(user.getPassword());
            recordByPhone.setDoctorsName(user.getRealname());
            recordByPhone.setDoctorsMobile(user.getPhone());
            recordByPhone.setDoctorsBirthday(user.getBirthday());
            recordByPhone.setDoctorsImg(user.getAvatar());
            recordByPhone.setDoctorsSex(user.getSex());

            if (doctorType != null) {
                recordByPhone.setDoctorsType(StringUtil.StrTrimInt(doctorType));
            }
            save(recordByPhone);
        }
    }

    @Override
    public DoctorIndexInfo getDoctorIndexInfo(Integer doctorId) {
        List<DtrdEntRdDoctorStatisticInfo> statisticInfoList = doctorStatisticInfoService.getDoctorStatisticInfoList(doctorId, null, 2);
        if (CollectionUtil.isNotEmpty(statisticInfoList)) {
            DoctorIndexInfo indexInfo = new DoctorIndexInfo();
            // 获取第一条，即最新的数据
            DtrdEntRdDoctorStatisticInfo newRecord = statisticInfoList.get(0);
            indexInfo = indexInfo.parseFromPO(newRecord);
            // 第二条数据，计算差值
            if (statisticInfoList.size() >= 2) {
                DtrdEntRdDoctorStatisticInfo secondRecord = statisticInfoList.get(1);
                if (secondRecord != null) {
                    indexInfo.countDiff(newRecord, secondRecord);
                }
            }
            // 统计服务患者总数
            List<DoctorStatisticsItem> servingPatientList = doctorPatientRlService.countServingPatient(doctorId);
            if (CollectionUtil.isNotEmpty(servingPatientList)) {
                // 有数据时即当前医生记录  取第一条即可
                indexInfo.setServingPatientCount(servingPatientList.get(0).getSummary());
            }
            // 总计联网血糖仪数
            List<DoctorStatisticsItem> bindDevicePatientList = doctorPatientRlService.countBindDevicePatient(doctorId);
            if (CollectionUtil.isNotEmpty(bindDevicePatientList)) {
                // 有数据时即当前医生记录  取第一条即可
                indexInfo.setGluDeviceCount(bindDevicePatientList.get(0).getSummary());

            }

            return indexInfo;
        }
        return null;
    }

    @Override
    public DoctorIndexInfo getTeamDoctorIndexInfo(Integer teamId) {
        List<DtrdEntRdDoctorStatisticInfo> statisticInfoList = doctorStatisticInfoService.getDoctorStatisticInfoList(null, teamId, 2);
        if (CollectionUtil.isNotEmpty(statisticInfoList)) {
            DoctorIndexInfo indexInfo = new DoctorIndexInfo();
            // 获取第一条，即最新的数据
            DtrdEntRdDoctorStatisticInfo newRecord = statisticInfoList.get(0);
            indexInfo = indexInfo.parseFromPO(newRecord);
            // 第二条数据，计算差值
            if (statisticInfoList.size() >= 2) {
                DtrdEntRdDoctorStatisticInfo secondRecord = statisticInfoList.get(1);
                if (secondRecord != null) {
                    indexInfo.countDiff(newRecord, secondRecord);
                }
            }
            List<Integer> doctorIdList = doctorTeamDoctorService.getTeamDoctorIdListByTeamId(teamId);
            // 统计服务患者总数
            List<DoctorStatisticsItem> servingPatientList = doctorPatientRlService.countServingPatientV2(doctorIdList);
            if (CollectionUtil.isNotEmpty(servingPatientList)) {
                // 有数据时即当前医生记录  取第一条即可
                indexInfo.setServingPatientCount(servingPatientList.get(0).getSummary());
            }
            // 总计联网血糖仪数
            List<DoctorStatisticsItem> bindDevicePatientList = doctorPatientRlService.countBindDevicePatientV2(doctorIdList);
            if (CollectionUtil.isNotEmpty(bindDevicePatientList)) {
                // 有数据时即当前医生记录  取第一条即可
                indexInfo.setGluDeviceCount(bindDevicePatientList.get(0).getSummary());
            }
            return indexInfo;
        }
        return null;
    }

    @Override
    public List<Integer> getDoctorTeamMemberByPatientId(Integer patientId) {
        // 获取患者对应的医生id
        Integer doctorId = doctorPatientRlService.getDoctorIdByPatientId(patientId);
        // 获取医生所属团队
        Integer teamId = doctorTeamDoctorService.geTeamIdByDoctorId(doctorId);
        List<Integer> doctorIds;
        if (teamId != null) {
            // 获取团队下所有医生id
            doctorIds = doctorTeamService.getTeamDoctorIds(teamId);
        } else {
            doctorIds = new ArrayList<>();
            doctorIds.add(doctorId);
        }
        return doctorIds;
    }


    @Override
    public DoctorIndexInfo getDoctorIndexInfoV2(List<Integer> doctorIdList) {
//        List<DtrdEntRdDoctorStatisticInfo> statisticInfoList = doctorStatisticInfoService.getDoctorStatisticInfoListV2(doctorIdList,2);
        return null;
    }
}
